package org.offsync.old.async

import collection.JavaConversions._
import java.nio.channels.spi.SelectorProvider
import java.nio.channels.SelectionKey
import java.nio.channels.ClosedChannelException
import java.nio.channels.ClosedSelectorException
import java.nio.channels.Selector
import java.nio.channels.spi.AbstractSelectableChannel
import org.offsync.rich._
import org.offsync.util.Disposer
import org.offsync.util.DisposableBase
import org.offsync.util.ScheduledExecutor
import scala.collection.{mutable => mutable}

class AsyncService extends DisposableBase {
  val selector: Selector = SelectorProvider.provider().openSelector()
  val executor = new ScheduledExecutor
  
  def register(
      selectableChannel: AbstractSelectableChannel,
      op: Int)(
          f: => Unit) = {
    selectableChannel.register(selector, op, f) // TODO: Fix
  }
  
  def invoke(f: () => Unit): AsyncReturn = {
    lock.synchronized {
      executor.execute {
        f()
      }
    }
    selector.wakeup()
    AsyncReturn
  }
  
  val thread = new Thread() {
    override def run() {
      try {
        while (isLive) {
          val selectCount = selector.select()
          
          if (selectCount == 0) {
            if (!executor.process()) {
              return
            }
          } else {
            selector.selectedKeys.iterator.consume { key =>
              val attachment = key.attachment
              val selectionAttachment = attachment.asInstanceOf[SelectionAttachment]
              selectionAttachment.perform(key.readyOps)
              key.cancel()
            }
          }
        }
      } catch {
        case e: ClosedSelectorException =>
        case e: ClosedChannelException =>
      } finally {
        AsyncService.super.onDispose()
      }
    }
  }
  
  thread.start();
  
  def start() = thread.start()

  protected override def onDispose(): Unit = {
    try selector.close() catch { case e => }
    
    super.onDispose()
  }
}
